package com.yuandian.bpm.bi.modules.quartz.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.csp.sentinel.util.StringUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yuandian.bpm.bi.modules.quartz.enums.TaskStateEnum;
import com.yuandian.bpm.bi.modules.quartz.mapper.ConfReportTaskInfoMapper;
import com.yuandian.bpm.bi.modules.quartz.mapper.ConfReportTaskLogMapper;
import com.yuandian.bpm.bi.modules.quartz.service.ConfReportTaskInfoService;
import com.yuandian.bpm.bi.modules.quartz.util.CronUtil;
import com.yuandian.bpm.bi.modules.quartz.util.MsgUtil;
import com.yuandian.bpm.bi.modules.quartz.util.QuartzUtil;
import com.yuandian.bpm.bi.modules.quartz.util.redis.RedisSendMsg;
import com.yuandian.bpm.bi.modules.quartz.vo.ConfReportRunningTaskVo;
import com.yuandian.bpm.bi.modules.quartz.vo.ConfReportTaskInfo;
import com.yuandian.bpm.bi.modules.quartz.vo.ConfReportTaskLog;
import com.yuandian.bpm.bi.modules.quartz.vo.RedisMsgParam;
import com.yuandian.bpm.common.core.util.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 报表定时任务表-Service实现
 * @author zfsn
 * @date 2023-6-19
 */
@Service
@Slf4j
public class ConfReportTaskInfoServiceImpl implements ConfReportTaskInfoService {

	@Autowired
	private ConfReportTaskInfoMapper confReportTaskInfoMapper;

	@Autowired
	private ConfReportTaskLogMapper confReportTaskLogMapper;

	@Autowired
	private RedisSendMsg redisSendMsg;

	@Autowired
	private QuartzUtil quartzUtil;

	private QuartzUtil quartzUtilStatic;

	@PostConstruct
	public void init() {
		quartzUtilStatic = this.quartzUtil;
	}

	/**
	 * 获取任务信息
	 * @param confReportTaskInfo 实例对象
	 * @return 通用返回对象
	 */
	@Override
	public R<ConfReportTaskInfo> getTaskInfoById(ConfReportTaskInfo param) {
		ConfReportTaskInfo confReportTaskInfo = confReportTaskInfoMapper.getOneTaskInfo(param);

		if (ObjectUtil.isNotNull(confReportTaskInfo)) {
			// 拼接通知方式字段
			if (StringUtil.isNotEmpty(confReportTaskInfo.getTaskNotificationPolicy())) {
				confReportTaskInfo.setTaskNotificationPolicyList(Arrays.asList(confReportTaskInfo.getTaskNotificationPolicy().split(",")));
			}

			// 拼接 邮件收件人列表
			if (StringUtil.isNotEmpty(confReportTaskInfo.getEmailRecipient())) {
				confReportTaskInfo.setEmailRecipientList(Arrays.asList(confReportTaskInfo.getEmailRecipient().split(",")));
			}

			// 拼接 抄送人列表
			if (StringUtil.isNotEmpty(confReportTaskInfo.getEmailCcBy())) {
				confReportTaskInfo.setEmailCcByList(Arrays.asList(confReportTaskInfo.getEmailCcBy().split(",")));
			}

			// 拼接 邮件密送人列表
			if (StringUtil.isNotEmpty(confReportTaskInfo.getEmailBccRecipient())) {
				confReportTaskInfo.setEmailBccRecipientList(Arrays.asList(confReportTaskInfo.getEmailBccRecipient().split(",")));
			}

			// 拼接 第三方接口收件人 列表
			if (StringUtil.isNotEmpty(confReportTaskInfo.getInterfaceRecipient())) {
				confReportTaskInfo.setInterfaceRecipientList(Arrays.asList(confReportTaskInfo.getInterfaceRecipient().split(",")));
			}

			// 处理任务结束类型(0：无限时间  1：设定结束时间  2：额外重复执行次数)
			int taskEndType = confReportTaskInfo.getTaskEndType();
			if (taskEndType == 1) {
				confReportTaskInfo.setTaskEndValue(confReportTaskInfo.getTaskEndTime());
			} else if(taskEndType == 2) {
				confReportTaskInfo.setTaskEndValue(confReportTaskInfo.getTaskTotalExecuteCount().toString());
			}
		}

		return R.ok(confReportTaskInfo);
	}

	/**
	 * 分页查询
	 * @param page 分页对象
	 * @param confReportTaskInfo 筛选条件
	 * @return 通用返回对象
	 */
	@Override
	public Page<ConfReportTaskInfo> getTaskInfoList(Page<ConfReportTaskInfo> page, ConfReportTaskInfo param) {
		Page<ConfReportTaskInfo> pageResult = confReportTaskInfoMapper.getTaskInfoList(page, param);
		if (pageResult != null && pageResult.getRecords() != null) {
			for (ConfReportTaskInfo confReportTaskInfo : pageResult.getRecords()) {
				// 拼接通知方式字段
				if (StringUtil.isNotEmpty(confReportTaskInfo.getTaskNotificationPolicy())) {
					confReportTaskInfo.setTaskNotificationPolicyList(Arrays.asList(confReportTaskInfo.getTaskNotificationPolicy().split(",")));
				}

				// 拼接 邮件收件人列表
				if (StringUtil.isNotEmpty(confReportTaskInfo.getEmailRecipient())) {
					confReportTaskInfo.setEmailRecipientList(Arrays.asList(confReportTaskInfo.getEmailRecipient().split(",")));
				}

				// 拼接 抄送人列表
				if (StringUtil.isNotEmpty(confReportTaskInfo.getEmailCcBy())) {
					confReportTaskInfo.setEmailCcByList(Arrays.asList(confReportTaskInfo.getEmailCcBy().split(",")));
				}

				// 拼接 邮件密送人列表
				if (StringUtil.isNotEmpty(confReportTaskInfo.getEmailBccRecipient())) {
					confReportTaskInfo.setEmailBccRecipientList(Arrays.asList(confReportTaskInfo.getEmailBccRecipient().split(",")));
				}

				// 拼接 第三方接口收件人 列表
				if (StringUtil.isNotEmpty(confReportTaskInfo.getInterfaceRecipient())) {
					confReportTaskInfo.setInterfaceRecipientList(Arrays.asList(confReportTaskInfo.getInterfaceRecipient().split(",")));
				}
			}
		}
		return pageResult;
	}


	/**
	 * 分页查询-执行中的任务
	 * @param page 分页对象
	 * @param confReportTaskInfo 筛选条件
	 * @return 通用返回对象
	 */
	@Override
	public Page<ConfReportRunningTaskVo> getRunningTaskList(Page<ConfReportRunningTaskVo> page, ConfReportTaskInfo confReportTaskInfo) {
		confReportTaskInfo.setTaskState(1);
		return confReportTaskInfoMapper.getRunningTaskList(page, confReportTaskInfo);
	}

	/**
	 * 分页查询日志信息
	 * @param confReportTaskInfo 筛选条件
	 * @return 通用返回对象
	 */
	@Override
	public Page<ConfReportTaskLog> getTaskLogList(Page<ConfReportTaskLog> page, ConfReportTaskInfo confReportTaskInfo) {
		return confReportTaskLogMapper.getLogInfoList(page, confReportTaskInfo);
	}


	/**
	 * 新增任务
	 * @param confReportTaskInfo 实例对象
	 * @return 通用返回对象
	 */
	@Override
	public R<Object> saveTaskInfo(ConfReportTaskInfo confReportTaskInfo) {

		// 判断任务是否重复
		int taskCount = confReportTaskInfoMapper.getTaskCount(confReportTaskInfo);
		if (taskCount > 0) { return R.failed("已存在同名任务"); }

		// 获取 cron 表达式
		confReportTaskInfo.setTaskCronExpression(CronUtil.getCronExpression(confReportTaskInfo));

		// 拼接通知方式字段
		if (CollectionUtil.isNotEmpty(confReportTaskInfo.getTaskNotificationPolicyList())) {
			confReportTaskInfo.setTaskNotificationPolicy(String.join(",", confReportTaskInfo.getTaskNotificationPolicyList()));
		}

		// 拼接 邮件收件人列表
		if (CollectionUtil.isNotEmpty(confReportTaskInfo.getEmailRecipientList())) {
			confReportTaskInfo.setEmailRecipient(String.join(",", confReportTaskInfo.getEmailRecipientList()));
		}

		// 拼接 抄送人列表
		if (CollectionUtil.isNotEmpty(confReportTaskInfo.getEmailCcByList())) {
			confReportTaskInfo.setEmailCcBy(String.join(",", confReportTaskInfo.getEmailCcByList()));
		}

		// 拼接 邮件密送人列表
		if (CollectionUtil.isNotEmpty(confReportTaskInfo.getEmailBccRecipientList())) {
			confReportTaskInfo.setEmailBccRecipient(String.join(",", confReportTaskInfo.getEmailBccRecipientList()));
		}

		// 拼接 第三方接口收件人 列表
		if (CollectionUtil.isNotEmpty(confReportTaskInfo.getInterfaceRecipientList())) {
			confReportTaskInfo.setInterfaceRecipient(String.join(",", confReportTaskInfo.getInterfaceRecipientList()));
		}

		// 处理任务结束类型(0：无限时间  1：设定结束时间  2：额外重复执行次数)
		int taskEndType = confReportTaskInfo.getTaskEndType();
		if (taskEndType == 1) {
			confReportTaskInfo.setTaskEndTime(confReportTaskInfo.getTaskEndValue());
		} else if(taskEndType == 2) {
			confReportTaskInfo.setTaskTotalExecuteCount(Integer.parseInt(confReportTaskInfo.getTaskEndValue()));
		}

		confReportTaskInfo.setTaskAlreadyExecuteCount(0);

		// 保存任务信息
		confReportTaskInfo.setTaskState(TaskStateEnum.RUNNING.getCode());
		// 文件处理策略, -1:文件永久保留(默认)  1:保留该任务最近1次的文件  7:保留该任务最近7次的文件
		confReportTaskInfo.setReportFileRetentionTime(confReportTaskInfo.getReportFileRetentionTime() == null ? -1 : confReportTaskInfo.getReportFileRetentionTime());
		int effectCount = confReportTaskInfoMapper.saveTaskInfo(confReportTaskInfo);

		// 执行任务
		if (effectCount > 0) { quartzUtilStatic.addJob(confReportTaskInfo); }

		return effectCount > 0 ? R.ok("任务添加成功") : R.failed("任务添加失败");
	}


	/**
	 * 通过主键更新任务
	 * @param confReportTaskInfo 实例对象
	 * @return 通用返回对象
	 */
	@Override
	public R<Object> updateTaskInfoById(ConfReportTaskInfo confReportTaskInfo) {

		// 判断任务是否在执行
		ConfReportTaskInfo taskInfo = confReportTaskInfoMapper.getOneTaskInfo(confReportTaskInfo);
		if (taskInfo == null) {
			log.warn("[修改任务][任务ID:{}]不存在", confReportTaskInfo.getId());
			return R.failed("修改失败,id为"+confReportTaskInfo.getId()+"的任务不存在");
		}
		if (TaskStateEnum.RUNNING.getCode() == taskInfo.getTaskState()) {
			log.warn("[修改任务][任务ID:{}]-失败：任务正在执行中", confReportTaskInfo.getId());
			return R.failed("修改失败, id为"+confReportTaskInfo.getId()+"的任务正在执行中");
		}

		// 判断任务是否重复
		int taskCount = confReportTaskInfoMapper.getTaskCount(confReportTaskInfo);
		if (taskCount > 0) { return R.failed("已存在同名任务"); }

		// 获取 cron 表达式
		confReportTaskInfo.setTaskCronExpression(CronUtil.getCronExpression(confReportTaskInfo));

		// 拼接通知方式字段
		if (CollectionUtil.isNotEmpty(confReportTaskInfo.getTaskNotificationPolicyList())) {
			confReportTaskInfo.setTaskNotificationPolicy(String.join(",", confReportTaskInfo.getTaskNotificationPolicyList()));
		}

		// 拼接 邮件收件人列表
		if (CollectionUtil.isNotEmpty(confReportTaskInfo.getEmailRecipientList())) {
			confReportTaskInfo.setEmailRecipient(String.join(",", confReportTaskInfo.getEmailRecipientList()));
		}

		// 拼接 抄送人列表
		if (CollectionUtil.isNotEmpty(confReportTaskInfo.getEmailCcByList())) {
			confReportTaskInfo.setEmailCcBy(String.join(",", confReportTaskInfo.getEmailCcByList()));
		}

		// 拼接 邮件密送人列表
		if (CollectionUtil.isNotEmpty(confReportTaskInfo.getEmailBccRecipientList())) {
			confReportTaskInfo.setEmailBccRecipient(String.join(",", confReportTaskInfo.getEmailBccRecipientList()));
		}

		// 拼接 第三方接口收件人 列表
		if (CollectionUtil.isNotEmpty(confReportTaskInfo.getInterfaceRecipientList())) {
			confReportTaskInfo.setInterfaceRecipient(String.join(",", confReportTaskInfo.getInterfaceRecipientList()));
		}

		// 处理任务结束类型(0：无限时间  1：设定结束时间  2：额外重复执行次数)
		int taskEndType = confReportTaskInfo.getTaskEndType();
		if (taskEndType == 1) {
			confReportTaskInfo.setTaskEndTime(confReportTaskInfo.getTaskEndValue());
			confReportTaskInfo.setTaskTotalExecuteCount(-1);
		} else if(taskEndType == 2) {
			confReportTaskInfo.setTaskTotalExecuteCount(Integer.parseInt(confReportTaskInfo.getTaskEndValue()));
			confReportTaskInfo.setTaskEndTime(null);
		}

		// 修改任务信息
		int effectCount = confReportTaskInfoMapper.updateTaskInfo(confReportTaskInfo);
		if (effectCount > 0) {
			log.warn("[修改任务][任务ID:{}]-成功", confReportTaskInfo.getId());
		} else {
			log.warn("[修改任务][任务ID:{}]-失败", confReportTaskInfo.getId());
			return R.failed("修改失败, id为"+confReportTaskInfo.getId()+"");
		}

		// 新增执行任务
		ConfReportTaskInfo param = confReportTaskInfoMapper.getOneTaskInfo(confReportTaskInfo);
		quartzUtilStatic.addJob(param);

		return R.ok("任务修改成功");
	}




	/**
	 * 删除任务任务参数
	 * 	 *
	 * @param confReportTaskInfo  @return	通用返回对象
	 */
	@Override
	public R<Object> deleteTaskByIds(ConfReportTaskInfo confReportTaskInfo) {

		// 判断是否存在正在执行的任务
		Page<ConfReportTaskInfo> runningTaskCount = confReportTaskInfoMapper.getTaskInfoList(new Page<>(1, 10), confReportTaskInfo);
		if (runningTaskCount != null && runningTaskCount.getRecords().size() > 0) {
			log.warn("[删除任务]-失败：存在正在运行的任务");
			return R.failed("删除失败,存在正在运行的任务");
		}

		// 广播删除Quartz任务
		List<Integer> ids = confReportTaskInfo.getIds();
		for (Integer id : ids) {
			RedisMsgParam redisMsgParam = new RedisMsgParam("delete", id);
			String msg = MsgUtil.getMsg(redisMsgParam);
			// 先redis通道发布命令
			redisSendMsg.sendMsg(msg);
			log.info("向redid发布命令:{}", msg);
		}

		// 删除数据表任务
		confReportTaskInfoMapper.deleteTaskByIds(confReportTaskInfo);
		log.info("[删除任务]-成功");

		return R.ok("任务删除成功");
	}

	/**
	 * 暂停任务
	 * @param ids 主键
	 * @param taskState 任务状态
	 * @return 通用返回对象 suspend
	 */
	@Override
	public R<Object> suspendTaskByIds(List<Integer> ids, int taskState) {

		// 广播发送 暂停任务命令
		for (Integer id : ids) {
			RedisMsgParam redisMsgParam = new RedisMsgParam("delete", id);
			String msg = MsgUtil.getMsg(redisMsgParam);
			// 先redis通道发布命令
			redisSendMsg.sendMsg(msg);
			log.info("向redid发布命令:{}", msg);
		}

		// 修改数据库表数据
		confReportTaskInfoMapper.startOrStopTask(ids, taskState);
		log.info("[暂停任务]-成功,任务ID: {}", ids);

		return R.ok("暂停成功");
	}


	/**
	 * 启动任务
	 * @param ids 主键
	 * @param taskState 任务状态
	 * @return 通用返回对象 suspend
	 */
	@Override
	public R<Object> startTaskByIds(List<Integer> ids, int taskState) {
		ConfReportTaskInfo params = new ConfReportTaskInfo();
		List<Integer> updatesIds = new ArrayList<>();
		List<Integer> runningIds = new ArrayList<>();

		params.setIds(ids);
		List<ConfReportTaskInfo> taskINfoList = confReportTaskInfoMapper.getTaskInfoNoPageList( params);
		for (ConfReportTaskInfo taskInfo : taskINfoList) {
			// '暂停' 的任务，或者 '停止 且 任务已执行次数<任务总需执行次数' 才进行启动
			if (TaskStateEnum.SUSPEND.getCode() == taskInfo.getTaskState() ||
					(TaskStateEnum.ENDED.getCode() == taskInfo.getTaskState() && taskInfo.getTaskAlreadyExecuteCount() < taskInfo.getTaskTotalExecuteCount())) {
				taskInfo.setTaskState(1);
				quartzUtilStatic.addJob(taskInfo);
				updatesIds.add(taskInfo.getId());
				log.info("[启动任务]-成功-任务ID: {}", taskInfo.getId());

			} else if (TaskStateEnum.RUNNING.getCode() == taskInfo.getTaskState()) {
				runningIds.add(taskInfo.getId());
				log.info("[启动任务]-失败-任务ID: {} 正在执行", taskInfo.getId());
			}
		}

		// 修改数据库表数据
		if (updatesIds.size() > 0) {
			confReportTaskInfoMapper.startOrStopTask(updatesIds, taskState);
			log.info("[启动任务]-成功,任务ID: {}", updatesIds);
			return R.ok("任务启动成功");
		} else if (runningIds.size() > 0) {
			return R.ok("任务启动失败, 该任务 "+ runningIds + " 处于执行状态");
		}

		return R.failed("任务启动失败");
	}

	/**
	 * 全局配置-运行失败提醒-平台提醒
	 * @param state 状态 0：不勾选平台提醒  1：勾选平台提醒
	 * @return 通用返回对象 suspend
	 */
	@Override
	public R<Object> platformReminderHandle(Integer state) {
		confReportTaskInfoMapper.platformReminderHandle(state);
		return R.ok();
	}

	/**
	 * 获取 全局配置-运行失败提醒-平台提醒
	 * @return 通用返回对象 suspend
	 */
	@Override
	public R<Object> getPlatformReminderState() {
		return R.ok(confReportTaskInfoMapper.getPlatformReminderState());
	}


}
